package com.zzf.concurrent.example.communication;

import lombok.extern.slf4j.Slf4j;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author GaoFeng2017
 * @date 2019/8/6 23:42
 */

@Slf4j
public class CaptureExample {

    private static final LinkedList<Page> WORKER_LIST = new LinkedList<>();
    private static final int MAX_WORKER = 5;

    public static void main(String[] args) {
        // 初始化采集线程
        List<Thread> threads = Arrays.asList("C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "C10")
                .stream()
                .map(CaptureExample::createCaptureThread)
                .collect(Collectors.toList());

        threads.forEach(Thread::start);

        // 让主线程等待采集线程结束
        threads.forEach(t -> {
            try {
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        log.info("all page is finished");
    }

    private static Thread createCaptureThread(String name) {
        return new Thread(() -> {
            double number = -1;
            synchronized (WORKER_LIST) {
                log.info("{} start capture...", Thread.currentThread().getName());
                while (WORKER_LIST.size() > MAX_WORKER) {
                    try {
                        WORKER_LIST.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                number = Math.random() * 1000;
                WORKER_LIST.add(new Page(number));
            }

            log.info("{} get page-{} content...", Thread.currentThread().getName(), number);

            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            log.info("{} is finished", Thread.currentThread().getName());
            // 唤醒所有空闲的采集线程
            synchronized (WORKER_LIST) {
                WORKER_LIST.notifyAll();
                WORKER_LIST.removeFirst();
            }
        }, name);
    }

    private static class Page {

        private double number;

        public Page(double number) {
            this.number = number;
        }

        public double getNumber() {
            return number;
        }

        public void setNumber(double number) {
            this.number = number;
        }
    }
}
